X /* open .rnsoft file containing soft ptrs to active file */
X
X tmpfp = fopen(softname,"r");
X if (tmpfp == Nullfp)
X writesoft = TRUE;
X
X /* allocate memory for rc file globals */
X grow_rc_arrays(1500);
X
X /* read in the .newsrc file */
X
X for (nextrcline = 0;
X (some_buf = get_a_line(buf,LBUFLEN,rcfp)) != Nullch;
X nextrcline++) {
X /* for each line in .newsrc */
X char tmpbuf[10];
X
X newng = nextrcline; /* get it into a register */
X length = len_last_line_got; /* side effect of get_a_line */
X if (length <= 1) { /* only a newline??? */
X nextrcline--; /* compensate for loop increment */
X continue;
X }
X if (newng >= maxrcline) /* check for overflow */
X grow_rc_arrays(maxrcline + 500);
X if (tmpfp != Nullfp && fgets(tmpbuf,10,tmpfp) != Nullch)
X softptr[newng] = atol(tmpbuf);
X else
X softptr[newng] = 0;
X some_buf[--length] = '\0'; /* wipe out newline */
X if (checkflag) /* no extra mallocs for -c */
X rcline[newng] = some_buf;
X else if (some_buf == buf) {
X rcline[newng] = savestr(some_buf);
X /* make a semipermanent copy */
X }
X else {
X /*NOSTRICT*/
X#ifndef lint
X some_buf = saferealloc(some_buf,(MEM_SIZE)(length+1));
X#endif /* lint */
X rcline[newng] = some_buf;
X }
X#ifdef NOTDEF
X if (strnEQ(some_buf,"to.",3)) { /* is this a non-newsgroup? */
X nextrcline--; /* destroy this line */
X continue;
X }
X#endif
X if (*some_buf == ' ' ||
X *some_buf == '\t' ||
X strnEQ(some_buf,"options",7)) { /* non-useful line? */
X toread[newng] = TR_JUNK;
X rcchar[newng] = ' ';
X rcnums[newng] = 0;
X continue;
X }
X parse_rcline(newng);
X if (rcchar[newng] == NEGCHAR) {
X toread[newng] = TR_UNSUB;
X continue;
X }
X
X /* now find out how much there is to read */
X
X if (!inlist(buf) || (suppress_cn && foundany && !paranoid))
X toread[newng] = TR_NONE; /* no need to calculate now */
X else
X set_toread(newng);
X#ifdef VERBOSE
X if (!checkflag && softmisses == 1) {
X softmisses++; /* lie a little */
X fputs("(Revising soft pointers--be patient.)\n",stdout) FLUSH;
X }
X#endif
X if (toread[newng] > TR_NONE) { /* anything unread? */
X if (!foundany) {
X starthere = newng;
X foundany = TRUE; /* remember that fact*/
X }
X if (suppress_cn) { /* if no listing desired */
X if (checkflag) { /* if that is all they wanted */
X finalize(1); /* then bomb out */
X }
X }
X else {
X#ifdef VERBOSE
X IF(verbose)
X printf("Unread news in %-40s %5ld article%s\n",
X rcline[newng],(long)toread[newng],
X toread[newng]==TR_ONE ? nullstr : "s") FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X printf("%s: %ld article%s\n",
X rcline[newng],(long)toread[newng],
X toread[newng]==TR_ONE ? nullstr : "s") FLUSH;
X#endif
X if (int_count) {
X countdown = 1;
X int_count = 0;
X }
X if (countdown) {
X if (! --countdown) {
X fputs("etc.\n",stdout) FLUSH;
X if (checkflag)
X finalize(1);
X suppress_cn = TRUE;
X }
X }
X }
X }
X }
X fclose(rcfp); /* close .newsrc */
X if (tmpfp != Nullfp)
X fclose(tmpfp); /* close .rnsoft */
X if (checkflag) { /* were we just checking? */
X finalize(foundany); /* tell them what we found */
X }
X if (paranoid)
X cleanup_rc();
X
X#ifdef HASHNG
X
X /* find a good hash size given num of newsgroups */
X
X hashsiz = maxrcline * 1.15;
X if ((hashsiz & 1) == 0) /* must be odd */
X hashsiz++;
X
X if (hashsiz <= activeitems)
X hashsiz = activeitems * 1.15;
X /* find one that's prime */
X while (! found) {
X for (i=3; ; i+=2) {
X if ( (float)(hashsiz)/i == hashsiz/i )
X break;
X if ( i > hashsiz/i ) {
X found = TRUE;
X break;
X }
X }
X if (! found)
X hashsiz += 2;
X }
X
X hashtbl = (short *) safemalloc( hashsiz * sizeof(short) );
X
X for (i=0; i<hashsiz; i++)
X hashtbl[i] = -1;
X
X if (!checkflag)
X for (i=0; i<nextrcline; i++)
X sethash(i);
X#endif
X
X#ifdef DEBUGGING
X if (debug & DEB_HASH) {
X page_init();
X for (i=0; i<hashsiz; i++) {
X sprintf(buf,"%d %d",i,hashtbl[i]);
X print_lines(buf,NOMARKING);
X }
X }
X#endif
X
X return foundany;
X}
X
static void
parse_rcline(ngnum)
NG_NUM ngnum;
X{
X#ifdef M_XENIX
X char *s; /* bypass a compiler bug (ugh!) */
X#else
X register char *s;
X#endif
X
X for (s = rcline[ngnum]; *s && *s != ':' && *s != NEGCHAR; s++) ;
X if (!*s && !checkflag) {
X#ifndef lint
X rcline[ngnum] = saferealloc(rcline[ngnum],
X (MEM_SIZE)(s - rcline[ngnum]) + 3);
X#endif /* lint */
X strcpy(s, ": ");
X }
X#ifdef USETHREADS
X if (*s == ':' && s[1] && s[2] == '0') {
X rcchar[ngnum] = '0';
X s[2] = '1';
X } else
X#endif
X rcchar[ngnum] = *s; /* salt away the : or ! */
X rcnums[ngnum] = (char)(s - rcline[ngnum]) + 1;
X /* remember where the numbers are */
X *s = '\0'; /* null terminate newsgroup name */
X}
X
void
abandon_ng(ngnum)
NG_NUM ngnum;
X{
X char *some_buf = Nullch;
X
X /* open .oldnewsrc and try to find the prior value for the group. */
X if ((rcfp = fopen(rcbname, "r")) != Nullfp) {
X int length = rcnums[ngnum] - 1;
X
X while ((some_buf = get_a_line(buf,LBUFLEN,rcfp)) != Nullch) {
X if (len_last_line_got <= 0)
X continue;
X some_buf[len_last_line_got-1] = '\0'; /* wipe out newline */
X if ((some_buf[length] == ':' || some_buf[length] == NEGCHAR)
X && strnEQ(rcline[ngnum], some_buf, length)) {
X break;
X }
X if (some_buf != buf)
X free(some_buf);
X }
X fclose(rcfp);
X } else if (errno != ENOENT) {
X printf("Unable to open %s.\n", rcbname) FLUSH;
X return;
X }
X if (some_buf == Nullch) {
X some_buf = rcline[ngnum] + rcnums[ngnum];
X if (*some_buf == ' ')
X some_buf++;
X *some_buf = '\0';
X#ifdef CACHEFIRST
X abs1st[ngnum] = 0; /* force group to be re-calculated */
X#endif
X }
X else {
X free(rcline[ngnum]);
X if (some_buf == buf) {
X rcline[ngnum] = savestr(some_buf);
X }
X else {
X /*NOSTRICT*/
X#ifndef lint
X some_buf = saferealloc(some_buf, (MEM_SIZE)(len_last_line_got));
X#endif /* lint */
X rcline[ngnum] = some_buf;
X }
X }
X parse_rcline(ngnum);
X if (rcchar[ngnum] == NEGCHAR)
X rcchar[ngnum] = ':';
X set_toread(ngnum);
X}
X
X/* try to find or add an explicitly specified newsgroup */
X/* returns TRUE if found or added, FALSE if not. */
X/* assumes that we are chdir'ed to SPOOL */
X
X#define ADDNEW_SUB ':'
X#define ADDNEW_UNSUB '!'
X
static int addnewbydefault = 0;
X
bool
get_ng(what,do_reloc)
char *what;
bool_int do_reloc;
X{
X char *ntoforget;
X char promptbuf[128];
X int autosub;
X
X#ifdef VERBOSE
X IF(verbose)
X ntoforget = "Type n to forget about this newsgroup.\n";
X ELSE
X#endif
X#ifdef TERSE
X ntoforget = "n to forget it.\n";
X#endif
X if (index(what,'/')) {
X dingaling();
X printf("\nBad newsgroup name.\n") FLUSH;
X return FALSE;
X }
X set_ngname(what);
X ng = find_ng(ngname);
X if (ng == nextrcline) { /* not in .newsrc? */
X
X#ifdef SERVER
X sprintf(ser_line, "GROUP %s", ngname);
X put_server(ser_line);
X if (nntp_get(ser_line, sizeof(ser_line)) < 0) {
X fprintf(stderr, "\nrrn: Unexpected close of server socket.\n");
X finalize(1);
X }
X if (*ser_line != CHAR_OK) {
X if (atoi(ser_line) != ERR_NOGROUP) {
X fprintf(stderr, "\nServer response to GROUP %s:\n%s\n",
X ngname, ser_line);
X finalize(1);
X }
X#else /* not SERVER */
X
X if (ng >= maxrcline) /* check for overflow */
X grow_rc_arrays(maxrcline + 25);
X
X if ((softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) {
X
X#endif /* SERVER */
X
X dingaling();
X#ifdef VERBOSE
X IF(verbose)
X printf("\nNewsgroup %s does not exist!\n",ngname) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X printf("\nNo %s!\n",ngname) FLUSH;
X#endif
X sleep(2);
X return FALSE;
X }
X autosub = auto_subscribe(ngname);
X if (!autosub) autosub = addnewbydefault;
X if (autosub) {
X printf("(Adding %s to end of your .newsrc %ssubscribed)\n",
X ngname, (autosub == ADDNEW_SUB) ? "" : "un");
X ng = add_newsgroup(ngname, autosub);
X do_reloc = FALSE;
X } else {
X#ifdef VERBOSE
X IF(verbose)
X sprintf(promptbuf,"\nNewsgroup %s not in .newsrc--subscribe? [ynYN] ",ngname);
X ELSE
X#endif
X#ifdef TERSE
X sprintf(promptbuf,"\nSubscribe %s? [ynYN] ",ngname);
X#endif
reask_add:
X in_char(promptbuf,'A');
X setdef(buf,"y");
X#ifdef VERIFY
X printcmd();
X#endif
X putchar('\n') FLUSH;
X if (*buf == 'h') {
X#ifdef VERBOSE
X IF(verbose)
X printf("Type y or SP to add %s to your .newsrc.\nType Y to add all new groups to the end of your .newsrc.\nType N to add all new groups to the end of your .newsrc unsubscribed.\n", ngname)
X FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("y or SP to add, Y to add all new groups, N to add all new groups unsubscribed\n",stdout) FLUSH;
X#endif
X fputs(ntoforget,stdout) FLUSH;
X goto reask_add;
X }
X else if (*buf == 'n' || *buf == 'q') {
X ng = add_newsgroup(ngname, '!');
X return FALSE;
X }
X else if (*buf == 'y') {
X ng = add_newsgroup(ngname, ':');
X do_reloc = TRUE;
X }
X else if (*buf == 'Y') {
X fputs(
X "(I'll add all new newsgroups (subscribed) to the end of your .newsrc.)\n",
X stdout);
X addnewbydefault = ADDNEW_SUB;
X printf("(Adding %s to end of your .newsrc subscribed)\n", ngname);
X ng = add_newsgroup(ngname, ':');
X do_reloc = FALSE;
X }
X else if (*buf == 'N') {
X fputs(
X "(I'll add all new newsgroups (unsubscribed) to the end of your .newsrc.)\n",
X stdout);
X addnewbydefault = ADDNEW_UNSUB;
X printf("(Adding %s to end of your .newsrc unsubscribed)\n", ngname);
X ng = add_newsgroup(ngname, '!');
X do_reloc = FALSE;
X }
X else {
X fputs(hforhelp,stdout) FLUSH;
X settle_down();
X goto reask_add;
X }
X }
X }
X else if (mode == 'i') /* adding new groups during init? */
X return FALSE;
X else if (rcchar[ng] == NEGCHAR) { /* unsubscribed? */
X#ifdef VERBOSE
X IF(verbose)
X sprintf(promptbuf,
X"\nNewsgroup %s is currently unsubscribed to--resubscribe? [yn] ",ngname)
X FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X sprintf(promptbuf,"\n%s unsubscribed--resubscribe? [yn] ",ngname)
X FLUSH;
X#endif
reask_unsub:
X in_char(promptbuf,'R');
X setdef(buf,"y");
X#ifdef VERIFY
X printcmd();
X#endif
X putchar('\n') FLUSH;
X if (*buf == 'h') {
X#ifdef VERBOSE
X IF(verbose)
X printf("Type y or SP to resubscribe to %s.\n", ngname) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("y or SP to resubscribe.\n",stdout) FLUSH;
X#endif
X fputs(ntoforget,stdout) FLUSH;
X goto reask_unsub;
X }
X else if (*buf == 'n' || *buf == 'q') {
X return FALSE;
X }
X else if (*buf == 'y') {
X#ifdef USETHREADS
X register char *cp = rcline[ng] + rcnums[ng];
X rcchar[ng] = (*cp && cp[1] == '0' ? '0' : ':');
X#else
X rcchar[ng] = ':';
X#endif
X do_reloc = FALSE;
X }
X else {
X fputs(hforhelp,stdout) FLUSH;
X settle_down();
X goto reask_unsub;
X }
X }
X
X /* now calculate how many unread articles in newsgroup */
X
X set_toread(ng);
X#ifdef RELOCATE
X if (do_reloc)
X ng = relocate_newsgroup(ng,-1);
X#endif
X return toread[ng] >= TR_NONE;
X}
X
X/* add a newsgroup to the .newsrc file (eventually) */
X
NG_NUM
add_newsgroup(ngn, c)
char *ngn;
char_int c;
X{
X register NG_NUM newng = nextrcline++;
X /* increment max rcline index */
X
X if (newng >= maxrcline) /* check for overflow */
X grow_rc_arrays(maxrcline + 25);
X
X rcnums[newng] = strlen(ngn) + 1;
X rcline[newng] = safemalloc((MEM_SIZE)(rcnums[newng] + 2));
X strcpy(rcline[newng],ngn); /* and copy over the name */
X strcpy(rcline[newng]+rcnums[newng], " ");
X rcchar[newng] = c; /* subscribe or unsubscribe */
X toread[newng] = TR_NONE; /* just for prettiness */
X#ifdef HASHNG
X sethash(newng); /* so we can find it again */
X#endif
X return newng;
X}
X
X#ifdef RELOCATE
NG_NUM
relocate_newsgroup(ngx,newng)
NG_NUM ngx;
NG_NUM newng;
X{
X char *dflt = (ngx!=current_ng ? "$^.L" : "$^L");
X char *tmprcline;
X ART_UNREAD tmptoread;
X char tmprcchar;
X char tmprcnums;
X ACT_POS tmpsoftptr;
X register NG_NUM i;
X#if defined(DEBUGGING) || defined(USETHREADS)
X ART_NUM tmpngmax;
X#endif
X#ifdef CACHEFIRST
X ART_NUM tmpabs1st;
X#endif
X
X starthere = 0; /* Disable this optimization */
X writesoft = TRUE; /* Update soft pointer file */
X if (ngx < nextrcline-1) {
X#ifdef HASHNG
X for (i=0; i<hashsiz; i++) {
X if (hashtbl[i] > ngx)
X --hashtbl[i];
X else if (hashtbl[i] == ngx)
X hashtbl[i] = nextrcline-1;
X }
X#endif
X tmprcline = rcline[ngx];
X tmptoread = toread[ngx];
X tmprcchar = rcchar[ngx];
X tmprcnums = rcnums[ngx];
X tmpsoftptr = softptr[ngx];
X#if defined(DEBUGGING) || defined(USETHREADS)
X tmpngmax = ngmax[ngx];
X#endif
X#ifdef CACHEFIRST
X tmpabs1st = abs1st[ngx];
X#endif
X for (i=ngx+1; i<nextrcline; i++) {
X rcline[i-1] = rcline[i];
X toread[i-1] = toread[i];
X rcchar[i-1] = rcchar[i];
X rcnums[i-1] = rcnums[i];
X softptr[i-1] = softptr[i];
X#if defined(DEBUGGING) || defined(USETHREADS)
X ngmax[i-1] = ngmax[i];
X#endif
X#ifdef CACHEFIRST
X abs1st[i-1] = abs1st[i];
X#endif
X }
X rcline[nextrcline-1] = tmprcline;
X toread[nextrcline-1] = tmptoread;
X rcchar[nextrcline-1] = tmprcchar;
X rcnums[nextrcline-1] = tmprcnums;
X softptr[nextrcline-1] = tmpsoftptr;
X#if defined(DEBUGGING) || defined(USETHREADS)
X ngmax[nextrcline-1] = tmpngmax;
X#endif
X#ifdef CACHEFIRST
X abs1st[nextrcline-1] = tmpabs1st;
X#endif
X }
X if (current_ng > ngx)
X current_ng--;
X if (newng < 0) {
X reask_reloc:
X unflush_output(); /* disable any ^O in effect */
X#ifdef VERBOSE
X IF(verbose)
X printf("\nPut newsgroup where? [%s] ", dflt);
X ELSE
X#endif
X#ifdef TERSE
X printf("\nPut where? [%s] ", dflt);
X#endif
X fflush(stdout);
X reinp_reloc:
X eat_typeahead();
X getcmd(buf);
X if (errno || *buf == '\f') {
X /* if return from stop signal */
X goto reask_reloc; /* give them a prompt again */
X }
X setdef(buf,dflt);
X#ifdef VERIFY
X printcmd();
X#endif
X if (*buf == 'h') {
X#ifdef VERBOSE
X IF(verbose) {
X printf("\n\n\
Type ^ to put the newsgroup first (position 0).\n\
Type $ to put the newsgroup last (position %d).\n", nextrcline-1);
X printf("\
Type . to put it before the current newsgroup (position %d).\n", current_ng);
X printf("\
Type -newsgroup name to put it before that newsgroup.\n\
Type +newsgroup name to put it after that newsgroup.\n\
Type a number between 0 and %d to put it at that position.\n", nextrcline-1);
X printf("\
Type L for a listing of newsgroups and their positions.\n") FLUSH;
X }
X ELSE
X#endif
X#ifdef TERSE
X {
X printf("\n\n\
X^ to put newsgroup first (pos 0).\n\
X$ to put last (pos %d).\n", nextrcline-1);
X printf("\
X. to put before current newsgroup (pos %d).\n", current_ng);
X printf("\
X-newsgroup to put before newsgroup.\n\
X+newsgroup to put after.\n\
number in 0-%d to put at that pos.\n", nextrcline-1);
X printf("\
L for list of .newsrc.\n") FLUSH;
X }
X#endif
X goto reask_reloc;
X }
X else if (*buf == 'L') {
X putchar('\n') FLUSH;
X list_newsgroups();
X goto reask_reloc;
X }
X else if (isdigit(*buf)) {
X if (!finish_command(TRUE)) /* get rest of command */
X goto reinp_reloc;
X newng = atol(buf);
X if (newng < 0)
X newng = 0;
X if (newng >= nextrcline)
X return nextrcline-1;
X }
X else if (*buf == '^') {
X putchar('\n') FLUSH;
X newng = 0;
X }
X else if (*buf == '$') {
X newng = nextrcline-1;
X }
X else if (*buf == '.') {
X putchar('\n') FLUSH;
X newng = current_ng;
X }
X else if (*buf == '-' || *buf == '+') {
X if (!finish_command(TRUE)) /* get rest of command */
X goto reinp_reloc;
X newng = find_ng(buf+1);
X if (newng == nextrcline) {
X fputs("Not found.",stdout) FLUSH;
X goto reask_reloc;
X }
X if (*buf == '+')
X newng++;
X }
X else {
X printf("\n%s",hforhelp) FLUSH;
X settle_down();
X goto reask_reloc;
X }
X }
X if (newng < nextrcline-1) {
X#ifdef HASHNG
X for (i=0; i<hashsiz; i++) {
X if (hashtbl[i] == nextrcline-1)
X hashtbl[i] = newng;
X else if (hashtbl[i] >= newng)
X ++hashtbl[i];
X }
X#endif
X tmprcline = rcline[nextrcline-1];
X tmptoread = toread[nextrcline-1];
X tmprcchar = rcchar[nextrcline-1];
X tmprcnums = rcnums[nextrcline-1];
X tmpsoftptr = softptr[nextrcline-1];
X#if defined(DEBUGGING) || defined(USETHREADS)
X tmpngmax = ngmax[nextrcline-1];
X#endif
X#ifdef CACHEFIRST
X tmpabs1st = abs1st[nextrcline-1];
X#endif
X for (i=nextrcline-2; i>=newng; i--) {
X rcline[i+1] = rcline[i];
X toread[i+1] = toread[i];
X rcchar[i+1] = rcchar[i];
X rcnums[i+1] = rcnums[i];
X softptr[i+1] = softptr[i];
X#if defined(DEBUGGING) || defined(USETHREADS)
X ngmax[i+1] = ngmax[i];
X#endif
X#ifdef CACHEFIRST
X abs1st[i+1] = abs1st[i];
X#endif
X }
X rcline[newng] = tmprcline;
X toread[newng] = tmptoread;
X rcchar[newng] = tmprcchar;
X rcnums[newng] = tmprcnums;
X softptr[newng] = tmpsoftptr;
X#if defined(DEBUGGING) || defined(USETHREADS)
X ngmax[newng] = tmpngmax;
X#endif
X#ifdef CACHEFIRST
X abs1st[newng] = tmpabs1st;
X#endif
X }
X if (current_ng >= newng)
X current_ng++;
X return newng;
X}
X#endif
X
X/* List out the newsrc with annotations */
X
void
list_newsgroups()
X{
X register NG_NUM i;
X char tmpbuf[2048];
X static char *status[] = {"(READ)","(UNSUB)","(BOGUS)","(JUNK)"};
X int cmd;
X
X page_init();
X print_lines("\
X # Status Newsgroup\n\
X",STANDOUT);
X for (i=0; i<nextrcline && !int_count; i++) {
X if (toread[i] >= 0)
X set_toread(i);
X#ifdef USETHREADS
X *(rcline[i] + rcnums[i] - 1) = RCCHAR(rcchar[i]);
X#else
X *(rcline[i] + rcnums[i] - 1) = rcchar[i];
X#endif
X if (toread[i] > 0)
X sprintf(tmpbuf,"%3d %6ld ",i,(long)toread[i]);
X else
X sprintf(tmpbuf,"%3d %7s ",i,status[-toread[i]]);
X safecpy(tmpbuf+13,rcline[i],2034);
X *(rcline[i] + rcnums[i] - 1) = '\0';
X if (cmd = print_lines(tmpbuf,NOMARKING)) {
X if (cmd > 0)
X pushchar(cmd);
X break;
X }
X }
X int_count = 0;
X}
X
X/* find a newsgroup in .newsrc */
X
NG_NUM
find_ng(ngnam)
char *ngnam;
X{
X register NG_NUM ngnum;
X#ifdef HASHNG
X register int hashix = hash(ngnam);
X register int incr = 1;
X
X while ((ngnum = hashtbl[hashix]) >= 0) {
X if (strEQ(rcline[ngnum], ngnam) && toread[ngnum] >= TR_UNSUB)
X return ngnum;
X hashix = (hashix + incr) % hashsiz;
X incr += 2; /* offsets from original are in n*2 */
X }
X return nextrcline; /* = notfound */
X
X#else /* just do linear search */
X
X for (ngnum = 0; ngnum < nextrcline; ngnum++) {
X if (strEQ(rcline[ngnum],ngnam))
X break;
X }
X return ngnum;
X#endif
X}
X
void
cleanup_rc()
X{
X register NG_NUM ngx;
X register NG_NUM bogosity = 0;
X
X#ifdef VERBOSE
X IF(verbose)
X fputs("Checking out your .newsrc--hang on a second...\n",stdout)
X FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("Checking .newsrc--hang on...\n",stdout) FLUSH;
X#endif
X for (ngx = 0; ngx < nextrcline; ngx++) {
X if (toread[ngx] >= TR_UNSUB) {
X set_toread(ngx); /* this may reset newsgroup */
X /* or declare it bogus */
X }
X if (toread[ngx] == TR_BOGUS)
X bogosity++;
X }
X for (ngx = nextrcline-1; ngx >= 0 && toread[ngx] == TR_BOGUS; ngx--)
X bogosity--; /* discount already moved ones */
X if (nextrcline > 5 && bogosity > nextrcline / 2) {
X fputs(
X"It looks like the active file is messed up. Contact your news administrator,\n\
X",stdout);
X fputs(
X"leave the \"bogus\" groups alone, and they may come back to normal. Maybe.\n\
X",stdout) FLUSH;
X }
X#ifdef RELOCATE
X else if (bogosity) {
X#ifdef VERBOSE
X IF(verbose)
X fputs("Moving bogus newsgroups to the end of your .newsrc.\n",
X stdout) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("Moving boguses to the end.\n",stdout) FLUSH;
X#endif
X for (; ngx >= 0; ngx--) {
X if (toread[ngx] == TR_BOGUS)
X relocate_newsgroup(ngx,nextrcline-1);
X }
X#ifdef DELBOGUS
reask_bogus:
X in_char("Delete bogus newsgroups? [ny] ", 'D');
X setdef(buf,"n");
X#ifdef VERIFY
X printcmd();
X#endif
X putchar('\n') FLUSH;
X if (*buf == 'h') {
X#ifdef VERBOSE
X IF(verbose)
X fputs("\
Type y to delete bogus newsgroups.\n\
Type n or SP to leave them at the end in case they return.\n\
X",stdout) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("y to delete, n to keep\n",stdout) FLUSH;
X#endif
X goto reask_bogus;
X }
X else if (*buf == 'n' || *buf == 'q')
X ;
X else if (*buf == 'y') {
X while (toread[nextrcline-1] == TR_BOGUS && nextrcline > 0)
X --nextrcline; /* real tough, huh? */
X }
X else {
X fputs(hforhelp,stdout) FLUSH;
X settle_down();
X goto reask_bogus;
X }
X#endif
X }
X#else
X#ifdef VERBOSE
X IF(verbose)
X fputs("You should edit bogus newsgroups out of your .newsrc.\n",
X stdout) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("Edit boguses from .newsrc.\n",stdout) FLUSH;
X#endif
X#endif
X paranoid = FALSE;
X}
X
X#ifdef HASHNG
X/* make an entry in the hash table for the current newsgroup */
X
void
sethash(thisng)
NG_NUM thisng;
X{
X register int hashix = hash(rcline[thisng]);
X register int incr = 1;
X#ifdef DEBUGGING
X static int hashhits = 0, hashtries = 0;
X#endif
X
X#ifdef DEBUGGING
X hashtries++;
X#endif
X while (hashtbl[hashix] >= 0) {
X#ifdef DEBUGGING
X hashhits++;
X if (debug & DEB_HASH) {
X printf(" Hash hits: %d / %d\n",hashhits, hashtries) FLUSH;
X }
X hashtries++;
X#endif
X hashix = (hashix + incr) % hashsiz;
X incr += 2; /* offsets from original are in n*2 */
X }
X hashtbl[hashix] = thisng;
X}
X
short prime[] = {1,2,-3,-5,7,11,-13,-17,19,23,-29,-31,37,41,-43,-47,53,57,-59,
X -61,67,71,-73,-79,83,89,-97,-101,1,1,1,1,1,1,1,1,1,1,1,1};
X
int
hash(ngnam)
register char *ngnam;
X{
X register int i = 0;
X register int ch;
X register int sum = 0;
X#ifdef DEBUGGING
X char *ngn = ngnam;
X#endif
X
X while (ch = *ngnam++) {
X sum += (ch + i) * prime[i]; /* gives ~ 10% hits at 25% full */
X i++;
X }
X#ifdef DEBUGGING
X if (debug & DEB_HASH)
X printf("hash(%s) => %d => %d\n",ngn, sum, (sum<0?-sum:sum)%hashsiz)
X FLUSH;
X#endif
X if (sum < 0)
X sum = -sum;
X return (sum % hashsiz);
X}
X
X#endif
X
void
newsrc_check()
X{
X rcfp = fopen(rcname,"r"); /* open it */
X if (rcfp == Nullfp) { /* not there? */
X#ifdef VERBOSE
X IF(verbose)
X fputs("\nTrying to set up a .newsrc file--running newsetup...\n\n\
X",stdout) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("Setting up .newsrc...\n",stdout) FLUSH;
X#endif
X if (doshell(sh,filexp(NEWSETUP)) ||
X (rcfp = fopen(rcname,"r")) == Nullfp) {
X#ifdef VERBOSE
X IF(verbose)
X fputs("\nCan't create a .newsrc--you must do it yourself.\n\
X",stdout) FLUSH;
X ELSE
X#endif
X#ifdef TERSE
X fputs("(Fatal)\n",stdout) FLUSH;
X#endif
X finalize(1);
X }
X }
X else {
X UNLINK(rcbname); /* unlink backup file name */
X link(rcname,rcbname); /* and backup current name */
X }
X}
X
X/* write out the (presumably) revised .newsrc */
X
void
write_rc()
X{
X register NG_NUM tmpng;
X register char *delim;
X
X rcfp = fopen(rctname, "w"); /* open .newnewsrc */
X if (rcfp == Nullfp) {
X printf(cantrecreate,".newsrc") FLUSH;
X finalize(1);
X }
X if (stat(rcname,&filestat)>=0) { /* preserve permissions */
X chmod(rctname,filestat.st_mode&0666);
X chown(rctname,filestat.st_uid,filestat.st_gid); /* if possible */
X }
X
X /* write out each line*/
X
X for (tmpng = 0; tmpng < nextrcline; tmpng++) {
X if (rcnums[tmpng]) {
X delim = rcline[tmpng] + rcnums[tmpng] - 1;
X#ifdef USETHREADS
X *delim = RCCHAR(rcchar[tmpng]);
X if (rcchar[tmpng] == '0' && delim[2] == '1')
X delim[2] = '0';
X#else
X *delim = rcchar[tmpng];
X#endif
X }
X else
X delim = Nullch;
X#ifdef DEBUGGING
X if (debug & DEB_NEWSRC_LINE)
X printf("%s\n",rcline[tmpng]) FLUSH;
X#endif
X if (fprintf(rcfp,"%s\n",rcline[tmpng]) < 0) {
X write_error:
X printf(cantrecreate,".newsrc") FLUSH;
X fclose(rcfp); /* close .newnewsrc */
X UNLINK(rctname);
X finalize(1);
X }
X if (delim) {
X *delim = '\0'; /* might still need this line */
X#ifdef USETHREADS
X if (rcchar[tmpng] == '0' && delim[2] == '0')
X delim[2] = '1';
X#endif
X }
X }
X fflush(rcfp);
X if (ferror(rcfp))
X goto write_error;
X
X fclose(rcfp); /* close .newnewsrc */
X UNLINK(rcname);
X#ifdef RENAME
X rename(rctname,rcname);
X#else
X link(rctname,rcname);
X UNLINK(rctname);
X#endif
X
X if (writesoft) {
X tmpfp = fopen(filexp(softname), "w"); /* open .rnsoft */
X if (tmpfp == Nullfp) {
X printf(cantcreate,filexp(softname)) FLUSH;
X return;
X }
X for (tmpng = 0; tmpng < nextrcline; tmpng++) {
X fprintf(tmpfp,"%ld\n",(long)softptr[tmpng]);
X }
X fclose(tmpfp);
X }
X}
X
void
get_old_rc()
X{
X UNLINK(rctname);
X#ifdef RENAME
X rename(rcname,rctname);
X rename(rcbname,rcname);
X#else
X link(rcname,rctname);
X UNLINK(rcname);
X link(rcbname,rcname);
X UNLINK(rcbname);
X#endif
X}
X
static char *
grow(ptr, elem, size)
char *ptr;
int elem;
int size;
X{
X if (ptr != NULL)
X return saferealloc(ptr, (MEM_SIZE)elem * size);
X else
X return safemalloc((MEM_SIZE)elem * size);
X}
X
static void
grow_rc_arrays(newsize)
int newsize;
X{
X#if defined(CACHEFIRST) || defined(USETHREADS)
X register int i;
X#endif
X
X#ifdef CACHEFIRST
X abs1st = (ART_NUM *) grow((char*)abs1st, newsize, sizeof(ART_NUM));
X#endif
X#if defined(DEBUGGING) || defined(USETHREADS)
X ngmax = (ART_NUM *) grow((char*)ngmax, newsize, sizeof(ART_NUM));
X#endif
X rcline = (char **) grow((char*)rcline, newsize, sizeof(char*));
X toread = (ART_UNREAD *) grow((char*)toread, newsize, sizeof(ART_UNREAD));
X rcchar = (char *) grow(rcchar, newsize, sizeof(char));
X rcnums = (char *) grow(rcnums, newsize, sizeof(char));
X softptr = (ACT_POS *) grow((char*)softptr, newsize, sizeof(ACT_POS));
X
X#if defined(CACHEFIRST) || defined(USETHREADS)
X for (i=maxrcline; i < newsize; i++) {
X# ifdef CACHEFIRST
X abs1st[i] = 0;
X# endif
X# ifdef USETHREADS
X ngmax[i] = 0;
X# endif
X }
X#endif /* CACHEFIRST || USETHREADS */
X maxrcline = newsize;
X return;
X}
END_OF_FILE
if test 27693 -ne `wc -c <'rcstuff.c'`; then
echo shar: \"'rcstuff.c'\" unpacked with wrong size!
fi
# end of 'rcstuff.c'
fi
echo shar: End of archive 9 \(of 13\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 13 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives: